
#include "stdafx.h"
#include "ReloadCode.h"
#include "ReloadPacket.h"
#include "ReloadConfigure.h"

SignatureAndHashAlgorithm::SignatureAndHashAlgorithm()
	:hash_(HashAlgorithm_None),signature_(SignatureAlgorithm_Anonymous)
{

}

SignatureAndHashAlgorithm::~SignatureAndHashAlgorithm()
{
	hash_ = HashAlgorithm_None;
	signature_ = SignatureAlgorithm_Anonymous;
}

retT SignatureAndHashAlgorithm::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(hash_));
	R(_pBuffer->ntohRead(signature_));
	READFROMBUFFER_END;
}

retT SignatureAndHashAlgorithm::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(hash_));
	R(_pBuffer->htonWrite(signature_));
	WRITETOBUFFER_END;
}

std::size_t SignatureAndHashAlgorithm::size()
{
	return sizeof(hash_) + sizeof(signature_);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////

GenericCertificate::GenericCertificate()
	:type_(CertificateType_X509)
{

}

GenericCertificate::~GenericCertificate()
{
	type_ = CertificateType_X509;
}

retT GenericCertificate::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(type_));
	R(certificate_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT GenericCertificate::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(type_));
	R(certificate_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t GenericCertificate::size()
{
	return sizeof(type_) + certificate_.size();
}

retT GenericCertificate::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(certificate_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

//////////////////////////////////////////////////////////////////////////////////////////////

SignerIdentityValue::SignerIdentityValue()
	:hashAlg_(HashAlgorithm_None),pIdentityType_(NULL)
{

}

SignerIdentityValue::~SignerIdentityValue()
{
	hashAlg_ = HashAlgorithm_None;
	pIdentityType_ = NULL;
}

retT SignerIdentityValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(hashAlg_));
	if(pIdentityType_)
	{
		switch(*pIdentityType_)
		{
		case SignerIdentityType_CertHash:R(certificateHash_.readFromBuffer(_pBuffer));break;
		case SignerIdentityType_CertHashNodeId:R(certificateNodeIdHash_.readFromBuffer(_pBuffer));break;
		case SignerIdentityType_None:/* empty *//* This structure may be extended with new types if necessary*/break;
		default:RET(INFO_PROTOCOL_RELOAD_SIGNERIDENTITYVALUE_UNKNOWN_TYPE);break;
		}
	}
	else
		RET(ERROR_COMMON_PTR_NULL);
	READFROMBUFFER_END;
}

retT SignerIdentityValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(hashAlg_));
	if(pIdentityType_)
	{
		switch(*pIdentityType_)
		{
		case SignerIdentityType_CertHash:R(certificateHash_.writeToBuffer(_pBuffer));break;
		case SignerIdentityType_CertHashNodeId:R(certificateNodeIdHash_.writeToBuffer(_pBuffer));break;
		case SignerIdentityType_None:/* empty *//* This structure may be extended with new types if necessary*/break;
		default:RET(INFO_PROTOCOL_RELOAD_SIGNERIDENTITYVALUE_UNKNOWN_TYPE);break;
		}
	}
	else
		RET(ERROR_COMMON_PTR_NULL);
	WRITETOBUFFER_END;
}

std::size_t SignerIdentityValue::size()
{
	std::size_t totalSize = 0;
	totalSize += sizeof(hashAlg_);
	if(pIdentityType_)
	{
		switch(*pIdentityType_)
		{
		case SignerIdentityType_CertHash:totalSize += certificateHash_.size();break;
		case SignerIdentityType_CertHashNodeId:totalSize += certificateNodeIdHash_.size();break;
		case SignerIdentityType_None:break;
		default:break;
		}
	}
	return totalSize;
}

retT SignerIdentityValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(certificateHash_.attachRootElement(_pRootElement));
	R(certificateNodeIdHash_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

retT SignerIdentityValue::init( SignerIdentity* _pSignerIdentity, SignerIdentityValue* _pSignerIdentityValue )
{
	_pSignerIdentityValue->pIdentityType_ = &_pSignerIdentity->identityType_;
	RETSUCCESS;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

SignerIdentity::SignerIdentity()
	:identityType_(SignerIdentityType_ReservedSignerIdentity),identity_()
{

}

SignerIdentity::SignerIdentity( const SignerIdentity& _signerIdentity )
	:PacketElement(_signerIdentity),identityType_(_signerIdentity.identityType_),identity_()
{
	for(std::size_t i = 0; i < _signerIdentity.identity_.size(); ++i)
	{
		identity_.push_back(_signerIdentity.identity_[i]);
		identity_[i].pIdentityType_ = &identityType_;
	}
}

SignerIdentity::~SignerIdentity()
{
	identityType_ = SignerIdentityType_ReservedSignerIdentity;
	identity_.clear();
}

retT SignerIdentity::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(identityType_));
	uint16	length = 0;
	R(_pBuffer->ntohRead(length));
	R(readContainerFromBuffer(_pBuffer, identity_, length, pRootElement_, (boost::function1< retT, SignerIdentityValue * >)boost::bind(&SignerIdentityValue::init, this, _1)));
	READFROMBUFFER_END;
}

retT SignerIdentity::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(identityType_));
	uint16	length = getTotalSize(identity_.begin(), identity_.end());
	R(_pBuffer->htonWrite(length));
	R(writeContainerToBuffer(_pBuffer, identity_.begin(), identity_.end()));
	WRITETOBUFFER_END;
}

std::size_t SignerIdentity::size()
{
	return sizeof(identityType_) + sizeof(uint16) + getTotalSize(identity_.begin(), identity_.end());
}

const SignerIdentity& SignerIdentity::operator=( const SignerIdentity& _signerIdentity )
{
	PacketElement::operator=(_signerIdentity);
	identityType_ = _signerIdentity.identityType_;
	identity_.clear();
	for(std::size_t i = 0; i < _signerIdentity.identity_.size(); ++i)
	{
		identity_.push_back(_signerIdentity.identity_[i]);
		identity_[i].pIdentityType_ = &identityType_;
	}
	return *this;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

Signature::Signature()
{

}

Signature::~Signature()
{

}

retT Signature::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(algorithm_.readFromBuffer(_pBuffer));
	R(identity_.readFromBuffer(_pBuffer));
	R(signatureValue_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT Signature::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(algorithm_.writeToBuffer(_pBuffer));
	R(identity_.writeToBuffer(_pBuffer));
	R(signatureValue_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t Signature::size()
{
	return algorithm_.size() + identity_.size() + signatureValue_.size();
}

retT Signature::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(algorithm_.attachRootElement(_pRootElement));
	R(identity_.attachRootElement(_pRootElement));
	R(signatureValue_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////

ReloadSecurityBlock::ReloadSecurityBlock()
{

}

ReloadSecurityBlock::~ReloadSecurityBlock()
{

}

retT ReloadSecurityBlock::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(certificates_.readFromBuffer(_pBuffer));
	R(signature_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT ReloadSecurityBlock::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(certificates_.writeToBuffer(_pBuffer));
	R(signature_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t ReloadSecurityBlock::size()
{
	return certificates_.size() + signature_.size();
}

retT ReloadSecurityBlock::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(certificates_.attachRootElement(_pRootElement));
	R(signature_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////

DataValue::DataValue()
	:exists_(Boolean_True)
{

}

DataValue::DataValue( BooleanT _exists )
	:exists_(_exists)
{

}

DataValue::DataValue( const std::vector<byte>& _array, BooleanT _exists /*= Boolean_True*/ )
	:exists_(_exists)
{
	R0(setValue(_array));
}

DataValue::DataValue( const char* _cstr, BooleanT _exists /*= Boolean_True*/ )
	:exists_(_exists)
{
	R0(setValue(_cstr));
}

DataValue::DataValue( const std::string& _str, BooleanT _exists /*= Boolean_True*/ )
	:exists_(_exists)
{
	R0(setValue(_str));
}

DataValue::~DataValue()
{
	exists_ = Boolean_False;
}

retT DataValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(exists_));
	R(value_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT DataValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(exists_));
	R(value_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t DataValue::size()
{
	return sizeof(exists_) + value_.size();
}

retT DataValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(value_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

retT DataValue::setValue( const std::vector<byte>& _array )
{
	value_.array_.clear();
	value_.array_.resize(_array.size());
	std::copy(_array.begin(), _array.end(), value_.array_.begin());
	RETSUCCESS;
}

retT DataValue::setValue( const char* _cstr )
{
	value_.array_.clear();
	value_.array_.resize(strlen(_cstr));
	for(std::size_t i = 0; i < value_.array_.size(); ++i)
		value_.array_[i] = (byte)_cstr[i];
	RETSUCCESS;
}

retT DataValue::setValue( const std::string& _str )
{
	value_.array_.clear();
	value_.array_.resize(_str.length());
	for(std::size_t i = 0; i < value_.array_.size(); ++i)
		value_.array_[i] = (byte)_str[i];
	RETSUCCESS;
}

std::string DataValue::toString()
{
	if(value_.array_.size() > 0)
		return std::string((char*)&value_.array_[0], value_.array_.size());
	return std::string();
}

/////////////////////////////////////////////////////////////////////////////////////

ArrayEntry::ArrayEntry()
	:index_(0)
{

}

ArrayEntry::~ArrayEntry()
{
	index_ = 0;
}

retT ArrayEntry::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(index_));
	R(value_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT ArrayEntry::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(index_));
	R(value_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t ArrayEntry::size()
{
	return sizeof(index_) + value_.size();
}

retT ArrayEntry::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(value_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////

DictionaryKey::DictionaryKey()
{

}

DictionaryKey::DictionaryKey( const std::vector<byte>& _array )
{
	R0(setValue(_array));
}

DictionaryKey::DictionaryKey( const char* _cstr )
{
	R0(setValue(_cstr));
}

DictionaryKey::DictionaryKey( const std::string& _str )
{
	R0(setValue(_str));
}

DictionaryKey::~DictionaryKey()
{

}

retT DictionaryKey::setValue( const std::vector<byte>& _array )
{
	array_.clear();
	array_.resize(_array.size());
	std::copy(_array.begin(), _array.end(), array_.begin());
	RETSUCCESS;
}

retT DictionaryKey::setValue( const char* _cstr )
{
	array_.clear();
	array_.resize(strlen(_cstr));
	for(std::size_t i = 0; i < array_.size(); ++i)
		array_[i] = (byte)_cstr[i];
	RETSUCCESS;
}

retT DictionaryKey::setValue( const std::string& _str )
{
	array_.clear();
	array_.resize(_str.length());
	for(std::size_t i = 0; i < array_.size(); ++i)
		array_[i] = (byte)_str[i];
	RETSUCCESS;
}

std::string DictionaryKey::toString()
{
	if(array_.size() > 0)
		return std::string((char*)&array_[0], array_.size());
	return std::string();
}

/////////////////////////////////////////////////////////////////////////////////////

DictionaryEntry::DictionaryEntry()
{

}

DictionaryEntry::~DictionaryEntry()
{

}

retT DictionaryEntry::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(key_.readFromBuffer(_pBuffer));
	R(value_.readFromBuffer(_pBuffer));
	READFROMBUFFER_END;
}

retT DictionaryEntry::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(key_.writeToBuffer(_pBuffer));
	R(value_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t DictionaryEntry::size()
{
	return key_.size() + value_.size();
}

retT DictionaryEntry::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(key_.attachRootElement(_pRootElement));
	R(value_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////

StoredDataValue::StoredDataValue()
	:pStoredData_(NULL)
{

}

StoredDataValue::~StoredDataValue()
{
	pStoredData_ = NULL;
}

retT StoredDataValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
	{
		switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:R(singleValueEntry_.readFromBuffer(_pBuffer));break;
		case DataModel_Array:R(arrayEntry_.readFromBuffer(_pBuffer));break;
		case DataModel_Dictionary:R(dictionaryEntry_.readFromBuffer(_pBuffer));break;
		default:break;
		}
	}
	else
		RET(ERROR_COMMON_PTR_NULL);
	READFROMBUFFER_END;
}

retT StoredDataValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
	{
		switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:R(singleValueEntry_.writeToBuffer(_pBuffer));break;
		case DataModel_Array:R(arrayEntry_.writeToBuffer(_pBuffer));break;
		case DataModel_Dictionary:R(dictionaryEntry_.writeToBuffer(_pBuffer));break;
		default:break;
		}
	}
	else
		RET(ERROR_COMMON_PTR_NULL);
	WRITETOBUFFER_END;
}

std::size_t StoredDataValue::size()
{
	std::size_t totalSize_ = 0;
	if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
	{
		switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:totalSize_ += singleValueEntry_.size();break;
		case DataModel_Array:totalSize_ += arrayEntry_.size();break;
		case DataModel_Dictionary:totalSize_ += dictionaryEntry_.size();break;
		default:break;
		}
	}
	return totalSize_;
}

retT StoredDataValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(singleValueEntry_.attachRootElement(_pRootElement));
	R(arrayEntry_.attachRootElement(_pRootElement));
	R(dictionaryEntry_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////

StoredData::StoredData()
	:length_(0),storageTime_(0),lifetime_(DEFAULT_STOREDDATA_LIFETIME),pKindData_(NULL)
{

}

StoredData::StoredData( const StoredData& _storedData )
	:PacketElement(_storedData),length_(_storedData.length_),storageTime_(_storedData.storageTime_),lifetime_(_storedData.lifetime_),value_(_storedData.value_),pKindData_(_storedData.pKindData_)
{
	value_.pStoredData_ = this;
}

StoredData::~StoredData()
{
	length_ = 0;
	storageTime_ = 0;
	lifetime_ = 0;
	pKindData_ = NULL;
}

retT StoredData::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(length_));
	if(pKindData_ && pKindData_->pKindBlock_)
	{
		R(_pBuffer->ntohRead(storageTime_));
		R(_pBuffer->ntohRead(lifetime_));
		R(value_.readFromBuffer(_pBuffer));
	}
	else
		R(_pBuffer->consume(length_));
	READFROMBUFFER_END;
}

retT StoredData::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	length_ = size() - sizeof(length_);
	R(_pBuffer->htonWrite(length_));
	R(_pBuffer->htonWrite(storageTime_));
	R(_pBuffer->htonWrite(lifetime_));
	R(value_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t StoredData::size()
{
	std::size_t totalSize = 0;
	totalSize += sizeof(length_);
	if(pKindData_ && pKindData_->pKindBlock_)
	{
		totalSize += sizeof(storageTime_) + sizeof(lifetime_) + value_.size();
	}
	else
		totalSize += length_;
	return totalSize;
}

retT StoredData::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(value_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

retT StoredData::init( KindData* _pKindData, StoredData* _pStoredData )
{
	_pStoredData->pKindData_ = _pKindData;
	_pStoredData->value_.pStoredData_ = _pStoredData;
	RETSUCCESS;
}

const StoredData& StoredData::operator=( const StoredData& _storedData )
{
	PacketElement::operator=(_storedData);
	length_ = _storedData.length_;
	storageTime_ = _storedData.storageTime_;
	lifetime_ = _storedData.lifetime_;
	value_ = _storedData.value_;
	pKindData_ = _storedData.pKindData_;
	value_.pStoredData_ = this;
	return *this;
}

/////////////////////////////////////////////////////////////////////////////////////

StoredDataPtr::StoredDataPtr()
	:pDataValue_(NULL)
{

}

StoredDataPtr::~StoredDataPtr()
{
	pDataValue_ = NULL;
}

/////////////////////////////////////////////////////////////////////////////////////

KindData::KindData()
	:kind_(0),generationCounter_(0),pKindBlock_(NULL),array_(),dictionary_()
{

}

KindData::KindData( const KindData& _kindData )
	:PacketElement(_kindData),kind_(_kindData.kind_),generationCounter_(_kindData.generationCounter_),pKindBlock_(_kindData.pKindBlock_)
{
	array_.clear();
	dictionary_.clear();
	for(std::list<StoredData>::const_iterator it = _kindData.values_.list_.begin(); it != _kindData.values_.list_.end(); ++it)
	{
		switch(pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:
			{
				if(it != _kindData.values_.list_.begin())
					R0(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE);
				R0(setSingleValueEntry(*it));
				break;
			}
		case DataModel_Array:R0(setArrayEntry(*it));break;
		case DataModel_Dictionary:R0(setDictionaryEntry(*it));break;
		default:R0(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
	}
}

KindData::~KindData()
{
	kind_ = 0;
	generationCounter_ = 0;
	pKindBlock_ = NULL;
	array_.clear();
	dictionary_.clear();
}

retT KindData::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(kind_));
	R(init(kind_));
	R(_pBuffer->ntohRead(generationCounter_));
	StructVarList<uint32, StoredData> values;
	R(values.attachRootElement(pRootElement_));
	R(values.readFromBuffer(_pBuffer, (boost::function1< retT, StoredData * >)boost::bind(&StoredData::init, this, _1)));
	if(pKindBlock_ != NULL)
	{
		for(std::list<StoredData>::iterator it = values.list_.begin(); it != values.list_.end(); ++it)
		{
			switch(pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:
				{
					if(it != values.list_.begin())
						RET(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE);
					R(setSingleValueEntry(*it));
					break;
				}
			case DataModel_Array:R(setArrayEntry(*it));break;
			case DataModel_Dictionary:R(setDictionaryEntry(*it));break;
			default:break;
			}
		}
	}
	READFROMBUFFER_END;
}

retT KindData::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(init(kind_));
	R(_pBuffer->htonWrite(kind_));
	R(_pBuffer->htonWrite(generationCounter_));
	R(values_.writeToBuffer(_pBuffer));
	WRITETOBUFFER_END;
}

std::size_t KindData::size()
{
	RU(init(kind_), 0);
	return sizeof(kind_) + sizeof(generationCounter_) + values_.size();
}

retT KindData::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(values_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

int KindData::init( KindId _kind )
{
	boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(_kind);
	if(it != overlayConfiguration_.requiredKinds_.end())
	{
		pKindBlock_ = &it->second;
		kind_ = _kind;
	}
	else
		pKindBlock_ = NULL;
	RETSUCCESS;
}

const KindData& KindData::operator=( const KindData& _kindData )
{
	PacketElement::operator=(_kindData);
	kind_ = _kindData.kind_;
	generationCounter_ = _kindData.generationCounter_;
	pKindBlock_ = _kindData.pKindBlock_;
	array_.clear();
	dictionary_.clear();
	for(std::list<StoredData>::const_iterator it = _kindData.values_.list_.begin(); it != _kindData.values_.list_.end(); ++it)
	{
		switch(pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:
			{
				if(it != _kindData.values_.list_.begin())
					RU(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE, *this);
				RU(setSingleValueEntry(*it), *this);
				break;
			}
		case DataModel_Array:RU(setArrayEntry(*it), *this);break;
		case DataModel_Dictionary:RU(setDictionaryEntry(*it), *this);break;
		default:RU(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE, *this);
		}
	}
	return *this;
}

retT KindData::setSingleValueEntry( const StoredData& _singleValueEntry )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(values_.list_.begin() == values_.list_.end())
		values_.list_.push_back(_singleValueEntry);
	else
		*values_.list_.begin() = _singleValueEntry;
	R(StoredData::init(this, &(*values_.list_.begin())));
	RETSUCCESS;
}

retT KindData::setSingleValueEntry( const DataValue& _singleDataValue )
{
	StoredData storedData;
	storedData.value_.singleValueEntry_ = _singleDataValue;
	R(setSingleValueEntry(storedData));
	RETSUCCESS;
}

retT KindData::setSingleValueEntry( const NumericVarArray<uint32, byte>& _value )
{
	StoredData storedData;
	storedData.value_.singleValueEntry_.exists_ = Boolean_True;
	storedData.value_.singleValueEntry_.value_ = _value;
	R(setSingleValueEntry(storedData));
	RETSUCCESS;
}

retT KindData::setSingleValueEntry( const std::vector<byte>& _array )
{
	StoredData storedData;
	storedData.value_.singleValueEntry_.exists_ = Boolean_True;
	storedData.value_.singleValueEntry_.value_ = _array;
	R(setSingleValueEntry(storedData));
	RETSUCCESS;
}

retT KindData::setSingleValueEntry( const char* _cstr )
{
	StoredData storedData;
	storedData.value_.singleValueEntry_.value_.array_.clear();
	storedData.value_.singleValueEntry_.value_.array_.resize(strlen(_cstr));
	for(std::size_t i = 0; i < storedData.value_.singleValueEntry_.value_.array_.size(); ++i)
		storedData.value_.singleValueEntry_.value_.array_[i] = (byte)_cstr[i];
	R(setSingleValueEntry(storedData));
	RETSUCCESS;
}

retT KindData::setSingleValueEntry( const std::string& _str )
{
	R(setSingleValueEntry(_str.c_str()));
	RETSUCCESS;
}

retT KindData::getSingleValueEntry( StoredDataPtr& _storedDataPtrOut )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(values_.list_.begin() == values_.list_.end())
	{
		_storedDataPtrOut.pStoredData_ = values_.list_.end();
		_storedDataPtrOut.pDataValue_ = NULL;
	}
	else
	{
		_storedDataPtrOut.pStoredData_ = values_.list_.begin();
		_storedDataPtrOut.pDataValue_ = &values_.list_.begin()->value_.singleValueEntry_;
	}
	RETSUCCESS;
}

retT KindData::deleteSingleValueEntry()
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	values_.list_.erase(values_.list_.begin());
	RETSUCCESS;
}

retT KindData::setArrayEntry( const StoredData& _arrayEntry )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	uint32 arrayEntryIndex = _arrayEntry.value_.arrayEntry_.index_;
	if(arrayEntryIndex == ARRAY_ENTRY_INDEX_END)
	{
		uint32 indexEnd = array_.size();
		while(indexEnd > 0 && (array_[indexEnd - 1].pDataValue_ == NULL || array_[indexEnd - 1].pDataValue_->exists_ == Boolean_False))
			--indexEnd;
		arrayEntryIndex = indexEnd;
	}
	if(array_.size() < arrayEntryIndex + 1)
		array_.resize(arrayEntryIndex + 1);
	if(array_[arrayEntryIndex].pDataValue_ == NULL)
	{
		values_.list_.push_back(_arrayEntry);
		array_[arrayEntryIndex].pStoredData_ = --values_.list_.end();
		array_[arrayEntryIndex].pDataValue_ = &array_[arrayEntryIndex].pStoredData_->value_.arrayEntry_.value_;
	}
	else
	{
		*array_[arrayEntryIndex].pStoredData_ = _arrayEntry;
		array_[arrayEntryIndex].pDataValue_ = &array_[arrayEntryIndex].pStoredData_->value_.arrayEntry_.value_;
	}
	R(StoredData::init(this, &(*array_[arrayEntryIndex].pStoredData_)));
	RETSUCCESS;
}

retT KindData::setArrayEntry( uint32 _index, const DataValue& _arrayDataValue )
{
	StoredData storedData;
	storedData.value_.arrayEntry_.index_ = _index;
	storedData.value_.arrayEntry_.value_ = _arrayDataValue;
	R(setArrayEntry(storedData));
	RETSUCCESS;
}

retT KindData::setArrayEntry( uint32 _index, const NumericVarArray<uint32, byte>& _value )
{
	StoredData storedData;
	storedData.value_.arrayEntry_.index_ = _index;
	storedData.value_.arrayEntry_.value_.exists_ = Boolean_True;
	storedData.value_.arrayEntry_.value_.value_ = _value;
	R(setArrayEntry(storedData));
	RETSUCCESS;
}

retT KindData::setArrayEntry( uint32 _index, const std::vector<byte>& _array )
{
	StoredData storedData;
	storedData.value_.arrayEntry_.index_ = _index;
	storedData.value_.arrayEntry_.value_.exists_ = Boolean_True;
	storedData.value_.arrayEntry_.value_.value_ = _array;
	R(setArrayEntry(storedData));
	RETSUCCESS;
}

retT KindData::setArrayEntry( uint32 _index, const char* _cstr )
{
	StoredData storedData;
	storedData.value_.arrayEntry_.index_ = _index;
	storedData.value_.arrayEntry_.value_.value_.array_.clear();
	storedData.value_.arrayEntry_.value_.value_.array_.resize(strlen(_cstr));
	for(std::size_t i = 0; i < storedData.value_.arrayEntry_.value_.value_.array_.size(); ++i)
		storedData.value_.arrayEntry_.value_.value_.array_[i] = (byte)_cstr[i];
	R(setArrayEntry(storedData));
	RETSUCCESS;
}

retT KindData::setArrayEntry( uint32 _index, const std::string& _str )
{
	R(setArrayEntry(_index, _str.c_str()));
	RETSUCCESS;
}

retT KindData::getArrayEntry( uint32 _index, StoredDataPtr& _storedDataPtrOut )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(array_.size() < _index + 1)
	{
		_storedDataPtrOut.pStoredData_ = values_.list_.end();
		_storedDataPtrOut.pDataValue_ = NULL;
	}
	else
	{
		_storedDataPtrOut.pStoredData_ = array_[_index].pStoredData_;
		_storedDataPtrOut.pDataValue_ = array_[_index].pDataValue_;
	}
	RETSUCCESS;
}

retT KindData::deleteArrayEntry( uint32 _index )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(array_.size() < _index + 1)
		RETSUCCESS;
	if(array_[_index].pDataValue_ == NULL)
		RETSUCCESS;
	values_.list_.erase(array_[_index].pStoredData_);
	array_[_index].pStoredData_ = values_.list_.end();
	array_[_index].pDataValue_ = NULL;
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const StoredData& _dictionaryEntry )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ == NULL)
	{
		values_.list_.push_back(_dictionaryEntry);
		dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_ = --values_.list_.end();
		dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ = &dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_->value_.dictionaryEntry_.value_;
	}
	else
	{
		*dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_ = _dictionaryEntry;
		dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ = &dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_->value_.dictionaryEntry_.value_;
	}
	R(StoredData::init(this, &(*dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_)));
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const DictionaryKey& _key, const DataValue& _dictionaryDataValue )
{
	StoredData storedData;
	storedData.value_.dictionaryEntry_.key_ = _key;
	storedData.value_.dictionaryEntry_.value_ = _dictionaryDataValue;
	R(setDictionaryEntry(storedData));
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const DictionaryKey& _key, const NumericVarArray<uint32, byte>& _value )
{
	StoredData storedData;
	storedData.value_.dictionaryEntry_.key_ = _key;
	storedData.value_.dictionaryEntry_.value_.exists_ = Boolean_True;
	storedData.value_.dictionaryEntry_.value_.value_ = _value;
	R(setDictionaryEntry(storedData));
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const DictionaryKey& _key, const std::vector<byte>& _array )
{
	StoredData storedData;
	storedData.value_.dictionaryEntry_.key_ = _key;
	storedData.value_.dictionaryEntry_.value_.exists_ = Boolean_True;
	storedData.value_.dictionaryEntry_.value_.value_ = _array;
	R(setDictionaryEntry(storedData));
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const DictionaryKey& _key, const char* _cstr )
{
	StoredData storedData;
	storedData.value_.dictionaryEntry_.key_ = _key;
	storedData.value_.dictionaryEntry_.value_.value_.array_.clear();
	storedData.value_.dictionaryEntry_.value_.value_.array_.resize(strlen(_cstr));
	for(std::size_t i = 0; i < storedData.value_.dictionaryEntry_.value_.value_.array_.size(); ++i)
		storedData.value_.dictionaryEntry_.value_.value_.array_[i] = (byte)_cstr[i];
	R(setDictionaryEntry(storedData));
	RETSUCCESS;
}

retT KindData::setDictionaryEntry( const DictionaryKey& _key, const std::string& _str )
{
	R(setDictionaryEntry(_key, _str.c_str()));
	RETSUCCESS;
}

retT KindData::getDictionaryEntry( const DictionaryKey& _key, StoredDataPtr& _storedDataPtrOut )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(dictionary_.find(_key) == dictionary_.end())
	{
		_storedDataPtrOut.pStoredData_ = values_.list_.end();
		_storedDataPtrOut.pDataValue_ = NULL;
	}
	else
	{
		_storedDataPtrOut.pStoredData_ = dictionary_[_key].pStoredData_;
		_storedDataPtrOut.pDataValue_ = dictionary_[_key].pDataValue_;
	}
	RETSUCCESS;
}

retT KindData::deleteDictionaryEntry( const DictionaryKey& _key )
{
	if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
		RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
	if(dictionary_.find(_key) == dictionary_.end())
		RETSUCCESS;
	if(dictionary_[_key].pDataValue_ == NULL)
	{
		dictionary_.erase(_key);
		RETSUCCESS;
	}
	values_.list_.erase(dictionary_[_key].pStoredData_);
	dictionary_.erase(_key);
	RETSUCCESS;
}

retT KindData::setEntry( const StoredData& _entry )
{
	if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
	{
		switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:R(setSingleValueEntry(_entry));break;
		case DataModel_Array:R(setArrayEntry(_entry));break;
		case DataModel_Dictionary:R(setDictionaryEntry(_entry));break;
		default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
	}
	else
	{
		RET(ERROR_COMMON_PTR_NULL);
	}
	RETSUCCESS;
}

retT KindData::getEntry( const StoredData& _entry, StoredDataPtr& _storedDataPtrOut )
{
	if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
	{
		switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:R(getSingleValueEntry(_storedDataPtrOut));break;
		case DataModel_Array:R(getArrayEntry(_entry.value_.arrayEntry_.index_, _storedDataPtrOut));break;
		case DataModel_Dictionary:R(getDictionaryEntry(_entry.value_.dictionaryEntry_.key_, _storedDataPtrOut));break;
		default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
	}
	else
	{
		RET(ERROR_COMMON_PTR_NULL);
	}
	RETSUCCESS;
}

retT KindData::deleteEntry( const StoredData& _entry )
{
	if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
	{
		switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:R(deleteSingleValueEntry());break;
		case DataModel_Array:R(deleteArrayEntry(_entry.value_.arrayEntry_.index_));break;
		case DataModel_Dictionary:R(deleteDictionaryEntry(_entry.value_.dictionaryEntry_.key_));break;
		default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
	}
	else
	{
		RET(ERROR_COMMON_PTR_NULL);
	}
	RETSUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////

StoreKindData::StoreKindData()
{

}

StoreKindData::~StoreKindData()
{

}

///////////////////////////////////////////////////////////////////////////////////

ArrayRange::ArrayRange()
	:first_(0),last_(0)
{

}

ArrayRange::~ArrayRange()
{
	first_ = 0;
	last_ = 0;
}

retT ArrayRange::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(first_));
	R(_pBuffer->ntohRead(last_));
	READFROMBUFFER_END;
}

retT ArrayRange::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	R(_pBuffer->htonWrite(first_));
	R(_pBuffer->htonWrite(last_));
	WRITETOBUFFER_END;
}

std::size_t ArrayRange::size()
{
	return sizeof(first_) + sizeof(last_);
}

bool operator<( const ArrayRange& _arrayRangeLeft, const ArrayRange& _arrayRangeRight )
{
	return _arrayRangeLeft.first_ < _arrayRangeRight.first_;
}

/////////////////////////////////////////////////////////////////////////////////////

StoredDataSpecifier::StoredDataSpecifier()
	:kind_(0),generation_(0),length_(0),pKindBlock_(NULL)
{

}

StoredDataSpecifier::~StoredDataSpecifier()
{
	kind_ = 0;
	generation_ = 0;
	length_ = 0;
	pKindBlock_ = NULL;
}

int StoredDataSpecifier::init( KindId _kind )
{
	boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(_kind);
	if(it != overlayConfiguration_.requiredKinds_.end())
	{
		pKindBlock_ = &it->second;
		kind_ = _kind;
	}
	else
		pKindBlock_ = NULL;
	RETSUCCESS;
}

retT StoredDataSpecifier::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	READFROMBUFFER_START;
	R(_pBuffer->ntohRead(kind_));
	R(init(kind_));
	R(_pBuffer->ntohRead(generation_));
	R(_pBuffer->ntohRead(length_));
	if(pKindBlock_ != NULL)
	{
		switch(pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:break;
		case DataModel_Array:R(modelSpecifier_.indices_.readFromBuffer(_pBuffer));break;
		case DataModel_Dictionary:R(modelSpecifier_.keys_.readFromBuffer(_pBuffer));break;
		default:R(_pBuffer->consume(length_));RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
	}
	else
		R(_pBuffer->consume(length_));
	READFROMBUFFER_END;
}

retT StoredDataSpecifier::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
{
	WRITETOBUFFER_START;
	boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(kind_);
	if(it != overlayConfiguration_.requiredKinds_.end())
	{
		pKindBlock_ = &it->second;
	}
	else
		RET(INFO_PROTOCOL_RELOAD_UNKNOWN_KIND);
	R(_pBuffer->htonWrite(kind_));
	R(_pBuffer->htonWrite(generation_));
	length_ = size() - sizeof(kind_) - sizeof(generation_) - sizeof(length_);
	R(_pBuffer->htonWrite(length_));
	switch(pKindBlock_->kind_.dataModel_)
	{
	case DataModel_Single:break;
	case DataModel_Array:R(modelSpecifier_.indices_.writeToBuffer(_pBuffer));break;
	case DataModel_Dictionary:R(modelSpecifier_.keys_.writeToBuffer(_pBuffer));break;
	default:R(_pBuffer->produce(length_));RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
	}
	WRITETOBUFFER_END;
}

std::size_t StoredDataSpecifier::size()
{
	RU(init(kind_), 0);
	std::size_t totalSize = 0;
	totalSize += sizeof(kind_);
	totalSize += sizeof(generation_);
	totalSize += sizeof(length_);
	if(pKindBlock_ != NULL)
	{
		switch(pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:break;
		case DataModel_Array:totalSize += modelSpecifier_.indices_.size();break;
		case DataModel_Dictionary:totalSize += modelSpecifier_.keys_.size();break;
		default:totalSize += length_;break;
		}
	}
	else
		totalSize += length_;
	return totalSize;
}

retT StoredDataSpecifier::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
{
	R(PacketElement::attachRootElement(_pRootElement));
	R(modelSpecifier_.indices_.attachRootElement(_pRootElement));
	R(modelSpecifier_.keys_.attachRootElement(_pRootElement));
	RETSUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////

FetchKindResponse::FetchKindResponse()
{

}

FetchKindResponse::~FetchKindResponse()
{

}
